//
// Created by 17775 on 2024/11/21.
//

#include "Beam_Line.h"

void Beam_Line::stopBeamLine() {
    RayCi_BeamLine_Recording_stop(_iBeamLineDocId);
}

void Beam_Line::clearBeamLine() {
    RayCi_BeamLine_Recording_clear(_iBeamLineDocId);
}

void Beam_Line::setFrameSpan(int frames) {
    bool bFrameSpanAvailable = false;
    RayCi_BeamLine_Recording_Settings_isFrameSpanAvailable(_iBeamLineDocId, &bFrameSpanAvailable);
    if(bFrameSpanAvailable) {
//        frames == 0 ? RayCi_BeamLine_Recording_Settings_setSingleShot(_iBeamLineDocId, true) :
//        RayCi_BeamLine_Recording_Settings_setFrameSpan(_iBeamLineDocId, frames);
        if(frames == 0) {
            setSingleShot(true);
        } else {
            RayCi_BeamLine_Recording_Settings_setFrameSpan(_iBeamLineDocId, frames);
        }
    }
}

void Beam_Line::setTimeSpan(double dTime) {
    bool bTimeSpanAvailable = false;
    RayCi_BeamStability_Recording_Settings_isTimeSpanAvailable(_iBeamLineDocId, &bTimeSpanAvailable);
    if(bTimeSpanAvailable) {
        if(dTime == 0) {
            setSingleShot(true);
        } else {
            RayCi_BeamStability_Recording_Settings_setTimeSpan(_iBeamLineDocId, dTime);
        }
    }
}

void Beam_Line::setSingleShot(bool bSingleShot) const {
    bool bSingleShotAvailable = false;
    RayCi_BeamLine_Recording_Settings_isSingleShotAvailable(_iBeamLineDocId, &bSingleShotAvailable);
    if(bSingleShotAvailable) {
        RayCi_BeamLine_Recording_Settings_setSingleShot(_iBeamLineDocId, bSingleShot);
    }
}

void Beam_Line::getBeamLineData() {
    int dataLength = 0;
    bool bRecording = true;
    while(bRecording) {
        RayCi_BeamLine_Recording_isRecording(_iBeamLineDocId, &bRecording);
    }
    RayCi_BeamLine_Chart_Data_getDataLength(_iBeamLineDocId, &dataLength);
    BeamLineDataBatch batchData;
    batchData.summedIntensity.resize(dataLength);
    batchData.summedIntensityValue.resize(dataLength);
    batchData.center.resize(dataLength);
    batchData.centerValue.resize(dataLength);
    batchData.width.resize(dataLength);
    batchData.widthValue.resize(dataLength);
    batchData.peakIntensity.resize(dataLength);
    batchData.peakIntensityValue.resize(dataLength);
    batchData.peakPosition.resize(dataLength);
    batchData.peakPositionValue.resize(dataLength);
    RayCi_BeamLine_Chart_Data_getDataAsBinary(_iBeamLineDocId, 0, batchData.summedIntensity.data(), &dataLength, batchData.summedIntensityValue.data(), &dataLength);
    RayCi_BeamLine_Chart_Data_getDataAsBinary(_iBeamLineDocId, 1, batchData.center.data(), &dataLength, batchData.centerValue.data(), &dataLength);
    RayCi_BeamLine_Chart_Data_getDataAsBinary(_iBeamLineDocId, 2, batchData.width.data(), &dataLength, batchData.widthValue.data(), &dataLength);
    RayCi_BeamLine_Chart_Data_getDataAsBinary(_iBeamLineDocId, 3, batchData.peakIntensity.data(), &dataLength, batchData.peakIntensityValue.data(), &dataLength);
    RayCi_BeamLine_Chart_Data_getDataAsBinary(_iBeamLineDocId, 4, batchData.peakPosition.data(), &dataLength, batchData.peakPositionValue.data(), &dataLength);
    bool _bCrossSectionValid = false;
    RayCi_Single_CrossSection_isValid(_iBeamLineDocId, 0, &_bCrossSectionValid);
    if(_bCrossSectionValid) {
        int iDataLength = 0;
        RayCi_Single_CrossSection_getDataLength(_iBeamLineDocId, 0, &iDataLength);
        if(iDataLength != 0) {
            std::vector<float> dXPositions_buffer;
            std::vector<float> dFitFunction_buffer;
            dXPositions_buffer.resize(iDataLength);
            dFitFunction_buffer.resize(iDataLength);
            batchData.YCrossPosition.resize(iDataLength);
            batchData.YCrossIntensity.resize(iDataLength);
            RayCi_Single_CrossSection_getDataAsBinary(_iBeamLineDocId, 0, dXPositions_buffer.data(), &iDataLength, batchData.YCrossPosition.data(),
                                                      &iDataLength, batchData.YCrossIntensity.data(), &iDataLength, dFitFunction_buffer.data(), &iDataLength);
        }
    }
    emit getBeamLineDataS(batchData);
}

std::shared_ptr<PowerProfileData<std::vector<float>>> Beam_Line::getCrossSectionData() {
    bool _bCrossSectionValid = false;
    std::shared_ptr<PowerProfileData<std::vector<float>>> crossData;
    RayCi_Single_CrossSection_isValid(_iBeamLineDocId, 0, &_bCrossSectionValid);
    if(_bCrossSectionValid) {
        int iDataLength = 0;
        RayCi_Single_CrossSection_getDataLength(_iBeamLineDocId, 0, &iDataLength);
        if(iDataLength != 0) {
            std::vector<float> dXPositions_buffer;
            std::vector<float> dYPositions_buffer;
            std::vector<float> dIntensity_buffer;
            std::vector<float> dFitFunction_buffer;
            dXPositions_buffer.resize(iDataLength);
            dYPositions_buffer.resize(iDataLength);
            dIntensity_buffer.resize(iDataLength);
            dFitFunction_buffer.resize(iDataLength);
            RayCi_Single_CrossSection_getDataAsBinary(_iBeamLineDocId, 0, dXPositions_buffer.data(), &iDataLength, dYPositions_buffer.data(),
                                                      &iDataLength, dIntensity_buffer.data(), &iDataLength, dFitFunction_buffer.data(), &iDataLength);
            crossData = std::make_shared<PowerProfileData<std::vector<float>>>(dXPositions_buffer, dIntensity_buffer);
        }
    }
    return crossData;
}

QString Beam_Line::getRecordingRemark() const {
    char szRemark_buffer[80] = {0};
    int nSize = sizeof(szRemark_buffer);
    bool success = RayCi_BeamLine_Recording_getRemarkA(_iBeamLineDocId, szRemark_buffer, &nSize);
    return success ? QString::fromLatin1(szRemark_buffer) : QString();
}

BeamLineResult Beam_Line::getBeamLineResult(bool bUncertainty) const {
    BeamLineResult beamLineResult;
    bool bYValid = false;
    bool bResidualYValid = false;
    bool bLineTiltValid = false;
    bool bLineCurvatureValid = false;
    bool bLineWidthValid = false;
    bool bLineLengthValid = false;
    bool bSummedIntensityValid = false;
    RayCi_BeamLine_Sequence_getItemCount(_iBeamLineDocId, &beamLineResult.dCount);
    RayCi_BeamLine_Analysis_Line_PositionY_isValid(_iBeamLineDocId, bUncertainty, &bYValid);
    RayCi_BeamLine_Analysis_Line_PositionYResidual_isValid(_iBeamLineDocId, bUncertainty, &bResidualYValid);
    RayCi_BeamLine_Analysis_Line_Tilt_isValid(_iBeamLineDocId, bUncertainty, &bLineTiltValid);
    RayCi_BeamLine_Analysis_Line_Curvature_isValid(_iBeamLineDocId, bUncertainty, &bLineCurvatureValid);
    RayCi_BeamLine_Analysis_Line_Width_isValid(_iBeamLineDocId, bUncertainty, &bLineWidthValid);
    RayCi_BeamLine_Cursor_isValid(_iBeamLineDocId, bUncertainty, &bLineLengthValid);
    RayCi_BeamLine_Cursor_Level_SummedIntensity_isValid(_iBeamLineDocId, 0, &bSummedIntensityValid);
    if (bYValid) {
        RayCi_BeamLine_Analysis_Line_PositionY_getPositionY(_iBeamLineDocId, bUncertainty, &beamLineResult.dPositionY);
        RayCi_BeamLine_Analysis_Line_PositionY_getPositionY(_iBeamLineDocId, !bUncertainty, &beamLineResult.dPositionUncertaintyY);
    }
    if (bResidualYValid) {
        RayCi_BeamLine_Analysis_Line_PositionYResidual_getPositionYResidual(_iBeamLineDocId, bUncertainty, &beamLineResult.dPositionResidualY);
        RayCi_BeamLine_Analysis_Line_PositionYResidual_getPositionYResidual(_iBeamLineDocId, !bUncertainty, &beamLineResult.dPositionResidualUncertaintyY);
    }
    if (bLineTiltValid) {
        RayCi_BeamLine_Analysis_Line_Tilt_getTilt(_iBeamLineDocId, bUncertainty, &beamLineResult.dLineTilt);
        RayCi_BeamLine_Analysis_Line_Tilt_getTilt(_iBeamLineDocId, !bUncertainty, &beamLineResult.dLineTiltUncertainty);
    }
    if (bLineCurvatureValid) {
        RayCi_BeamLine_Analysis_Line_Curvature_getCurvature(_iBeamLineDocId, bUncertainty, &beamLineResult.dLineCurvature);
        RayCi_BeamLine_Analysis_Line_Curvature_getCurvature(_iBeamLineDocId, !bUncertainty, &beamLineResult.dLineCurvatureUncertainty);
    }
    if (bLineWidthValid) {
        RayCi_BeamLine_Analysis_Line_Width_getWidth(_iBeamLineDocId, bUncertainty, &beamLineResult.dWidth);
        RayCi_BeamLine_Analysis_Line_Width_getWidth(_iBeamLineDocId, !bUncertainty, &beamLineResult.dWidthUncertainty);
    }
    if (bLineLengthValid) {
        RayCi_BeamLine_Cursor_getDistance(_iBeamLineDocId, 0, &beamLineResult.dLineLength);
    }
    if (bSummedIntensityValid) {
        RayCi_BeamLine_Cursor_Level_Settings_getRange(_iBeamLineDocId, 0, &beamLineResult.dHomogeneity);
    }
    return beamLineResult;
}

int Beam_Line::getItemCount() const {
    int nItemCount = 0;
    RayCi_BeamLine_Sequence_getItemCount(_iBeamLineDocId, &nItemCount);
    return nItemCount;
}

QString Beam_Line::getItemInfo(int index) const {
    char szInfo_buffer[80] = {0};
    int nSize = sizeof(szInfo_buffer);
    RayCi_BeamLine_Sequence_Item_getInfoA(_iBeamLineDocId, index, szInfo_buffer, &nSize);
    return QString::fromLatin1(szInfo_buffer);
}

void Beam_Line::setCurrentItem(int index) const {
    if(index < 0) return;
    RayCi_BeamLine_Sequence_setCurrentItem(_iBeamLineDocId, index);
}

void Beam_Line::exportReport() {
    RayCi_createDirectoryA("C:\\RayCi\\BeamLine");
    OPENFILENAMEA ofn;
    char szFile[260] = { 0 }; // 确保文件缓冲区初始化为空
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = GetActiveWindow(); // 确保传递有效窗口句柄
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile) - 1;
    ofn.lpstrFilter = "PDF Files(*.pdf)\0*.pdf*\0All Files(*.*)\0*.*\0\0";
    ofn.nFilterIndex = 1;
    ofn.lpstrInitialDir = "C:\\RayCi\\BeamLine";
    ofn.lpstrTitle = "Save Report As";
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT;

    if (GetSaveFileNameA(&ofn) == TRUE) {
        const char* reportPathName = ofn.lpstrFile;
        std::string reportPathWithExtension = std::string(reportPathName) + ".pdf";
        RayCi_BeamLine_Report_exportA(_iBeamLineDocId, reportPathWithExtension.c_str());
        ShellExecuteA(nullptr, "open", reportPathWithExtension.c_str(), nullptr, nullptr, SW_SHOWNORMAL);
    } else {
        DWORD error = CommDlgExtendedError();
        if (error != 0) {

        }
        MessageBoxA(nullptr, "Export was cancelled.", "Info", MB_OK | MB_ICONINFORMATION);
    }
}


void Beam_Line::close(bool bWaitWhileClosing) {
    RayCi_BeamLine_close(_iBeamLineDocId, bWaitWhileClosing);
}